// 布订阅模式，实现一个EventBus类，具备on、off、once、emit方法
class EventBus {
    constructor() {
      // events对象用于存储事件及其对应的回调函数
      this.events = {};
    }
  
    on(eventName, callback) {
      // 如果事件不存在，则先创建一个数组用于存储回调函数
      if (!this.events[eventName]) {
        this.events[eventName] = [];
      }
      // 将回调函数添加到事件对应的数组中
      this.events[eventName].push(callback);
    }
  
    off(eventName, callback) {
      // 如果事件存在，则移除指定的回调函数
      if (this.events[eventName]) {
        const index = this.events[eventName].indexOf(callback);
        if (index !== -1) {
          this.events[eventName].splice(index, 1);
        }
      }
    }
  
    once(eventName, callback) {
      // 包装一层函数，执行后立即将自身移除
      const wrapper = (...args) => {
        callback.apply(this, args);
        this.off(eventName, wrapper);
      };
      // 调用on方法添加回调函数
      this.on(eventName, wrapper);
    }
  
    emit(eventName, ...args) {
      // 依次执行事件对应的所有回调函数
      if (this.events[eventName]) {
        this.events[eventName].forEach(callback => {
          callback.apply(this, args);
        });
      }
    }
  }
  
const bus = new EventBus();

// 添加事件监听
bus.on('event1', (arg1, arg2) => {
  console.log(`event1: ${arg1}, ${arg2}`);
});

// 添加一次性事件监听
bus.once('event2', arg => {
  console.log(`event2: ${arg}`);
});

// 触发事件
bus.emit('event1', 'hello', 'world'); // 输出：event1: hello, world
bus.emit('event2', 'foo'); // 输出：event2: foo
bus.emit('event2', 'bar'); // 不输出任何内容，因为之前的回调函数已被移除
